package utils;


import java.io.File;
import java.io.IOException;
import java.nio.file.StandardCopyOption;

/**
 * Author: liaohailong
 * Date: 2024/3/27
 * Time: 14:05
 * Description:
 **/
public class FileUtils {

    /**
     * Copies a regular file from one path to another, preserving file attributes. If the
     * destination file exists, it gets overwritten.
     */
    public static void copyFile(File from, File to) throws IOException {
        java.nio.file.Files.copy(
                from.toPath(),
                to.toPath(),
                StandardCopyOption.COPY_ATTRIBUTES,
                StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * Copies a directory from one path to another. If the destination directory exists, the file
     * contents are merged and files from the source directory overwrite files in the destination.
     */
    public static void copyDirectory(File from, File to) throws IOException {
        checkArgument(from.isDirectory(), "Source path is not a directory.");
        checkArgument(
                !to.exists() || to.isDirectory(),
                "Destination path exists and is not a directory.");

        mkdirs(to);
        File[] children = from.listFiles();
        if (children != null) {
            for (File child : children) {
                if (child.isFile()) {
                    copyFileToDirectory(child, to);
                } else if (child.isDirectory()) {
                    copyDirectoryToDirectory(child, to);
                } else {
                    throw new IllegalArgumentException(
                            "Don't know how to copy file " + child.getAbsolutePath());
                }
            }
        }
    }

    /**
     * Creates a directory, if it doesn't exist.
     *
     * @param folder the directory to create, may already exist
     * @return {@code folder}
     */

    public static File mkdirs(File folder) {
        // attempt to create first.
        // if failure only throw if folder does not exist.
        // This makes this method able to create the same folder(s) from different thread
        if (!folder.mkdirs() && !folder.isDirectory()) {
            throw new RuntimeException("Cannot create directory " + folder);
        }

        return folder;
    }

    /**
     * Makes a copy of the given file in the specified directory, preserving the name and file
     * attributes.
     */
    public static void copyFileToDirectory(final File from, final File to)
            throws IOException {
        copyFile(from, new File(to, from.getName()));
    }

    /**
     * Makes a copy of the given directory in the specified destination directory.
     *
     * @see #copyDirectory(File, File)
     */
    public static void copyDirectoryToDirectory(final File from, final File to)
            throws IOException {
        copyDirectory(from, new File(to, from.getName()));
    }


    /**
     * Ensures the truth of an expression involving one or more parameters to the calling method.
     *
     * @param expression   a boolean expression
     * @param errorMessage the exception message to use if the check fails; will be converted to a
     *                     string using {@link String#valueOf(Object)}
     * @throws IllegalArgumentException if {@code expression} is false
     */
    public static void checkArgument(boolean expression, Object errorMessage) {
        if (!expression) {
            throw new IllegalArgumentException(String.valueOf(errorMessage));
        }
    }
}
